package uniquePathsWithObstacles

/*
一个机器人位于一个 m x n 网格的左上角 （起始点在下图中标记为 “Start” ）。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角（在下图中标记为 “Finish”）。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径？

网格中的障碍物和空位置分别用 1 和 0 来表示。

*/
func uniquePathsWithObstacles(obstacleGrid [][]int) int {
	m, n := len(obstacleGrid), len(obstacleGrid[0])
	// dp[i][j]表示从dp[0][0]开始到达的路径条数
	dp := make([][]int, m)
	for i := 0; i < m; i++ {
		dp[i] = make([]int, n)
	}

	for i := 0; i < n; i++ {
		// 遇到障碍物，此条路径往后的都设置为0，因为没法横着到达
		if obstacleGrid[0][i] == 1 {
			break
		}
		dp[0][i] = 1
	}
	for i := 0; i < m; i++ {
		// 遇到障碍物，此条路径往后的都设置为0，因为没法竖着到达
		if obstacleGrid[i][0] == 1 {
			break
		}
		dp[i][0] = 1
	}

	for i := 1; i < m; i++ {
		for j := 1; j < n; j++ {
			// 遇到障碍物，该点不计算，默认路径和为0
			if obstacleGrid[i][j] == 1 {
				continue
			}
			// 只能往右或者往下达到dp[i][j]
			dp[i][j] = dp[i-1][j] + dp[i][j-1]
		}
	}

	return dp[m-1][n-1]
}

// dfs 方法会超出时间限制
func uniquePathsWithObstaclesDFS(obstacleGrid [][]int) int {
	ans := 0
	m, n := len(obstacleGrid), len(obstacleGrid[0])
	var dfs func(obstacleGrid [][]int, i, j int)
	dfs = func(grid [][]int, i, j int) {
		if i >= m || j >= n || grid[i][j] == 1 {
			return
		}
		if i == m-1 && j == n-1 {
			ans++
		}
		dfs(grid, i+1, j)
		dfs(grid, i, j+1)
	}

	dfs(obstacleGrid, 0, 0)
	return ans
}
